home *** CD-ROM | disk | FTP | other *** search
- .!****************************************************************************
- .!
- .! ANTIC PUBLISHING INC., COPYRIGHT 1985. REPRINTED BY PERMISSION.
- .!
- .! ** Professional GEM ** by Tim Oren
- .!
- .! Proff File by ST enthusiasts at
- .! Case Western Reserve University
- .! Cleveland, Ohio
- .! uucp : decvax!cwruecmp!bammi
- .! csnet: bammi@case
- .! arpa : bammi%case@csnet-relay
- .! compuserve: 71515,155
- .!
- .!****************************************************************************
- .!
- .!
- .!****************************************************************************
- .!
- .! Begin Part 4
- .!
- .!****************************************************************************
- .!
- .PART IV Resource Structure
- .PP
- Welcome to the fourth installment of ST PRO GEM. We are about to delve into
- the mysteries of GEM resource structure, and then use this knowledge to create
- some useful utilities for handling dialogs. As with the past columns, there is
- once again a download file. You will find it under the name GEMCL4.C in the
- ATARI 16-bit Forum (GO PCS-58).
- .PP
- The first and largest part of the download contains a C image of a sample
- resource file. To create this listing, I used the GEM Resource Construction
- Set to create a dummy resource with three dialogs including examples of all
- object types, then enabled the C output option and saved the resource. If you
- have access to a copy of RCS, I suggest that you create your own listing in
- order to get a feel for the results. Then, using either listing as a roadmap
- to the resource, you can follow along as we enter...
- .SH A MAZE OF TWISTY LITTLE PASSAGES.
- While a GEM resource is loaded as a block of binary information, it
- is actually composed of a number of different data structures. These
- structures are linked together in a rather tangled hierarchy. Our
- first job is to map this linkage system.
- .PP
- The topmost structure in a resource file is the resource header. This is an
- array of words containing the size and offset within the resource of the other
- structures which follow. This information is used by GEM during the resource
- load process, and you should never need to access it. (The resource header does
- not appear in the C output file; it is generated by the RSCREATE utility if the
- C file is used to recreate the resource.)
- .PP
- The next structure of interest is the tree index. This is an array of long
- pointers, each of which addresses the beginning of an object tree. Again, you
- wouldn't normally access this structure directly. The GEM rsrc_gaddr call uses
- it when finding trees' addresses. This structure is called "rs_trindex" in the
- C output.
- .PP
- If you look at the contents of rs_trindex you will notice that the values are
- integers, instead of the pointers I described. What has happened is that RCS
- has converted the pointers to indices into the object array. (If you actually
- used the C file to recreate the resource file, then the pointers would be
- regenerated by RSCREATE.)
- .PP
- Now you can follow the link from rs_trindex to the objects stored in
- rs_object. Take (for instance) the second entry in rs_trindex and count down
- that many lines in rs_object. The following line (object) should start with a
- -1. This indicates that it is the root object of a tree. The following objects
- down to the next root belong to that tree. We'll pass over the details of
- inter-object linkage for now, leaving it for a later column.
- .PP
- There are a number of different fields in an object, but right now we'll
- concentrate on two of them: OB_TYPE and OB_SPEC. The OB_TYPE is the field which
- contains mnemonics like G_STRING and G_BOX indicating the type of the object.
- The OB_SPEC is the only field in each object which is a LONG - you can tell it
- by the L after the number.
- .PP
- What's in OB_SPEC depends on the object type, so we need to talk about what
- kinds of objects are available, what you might use them for, and finally how
- they use the OB_SPEC field.
- .PP
- The box type objects are G_BOX, G_IBOX, and G_BOXCHAR. A G_BOX is an opaque
- rectangle, with an optional border. It's used to create a solid patch of color
- or pattern on which to place other objects. For instance, the background of a
- dialog is a G_BOX.
- .PP
- A G_IBOX is a hollow box which has only a border. (If the border has no
- thickness, then the box is "invisible", hence the name.) The favorite use for
- IBOXes is to hold radio buttons. There is also one neat trick you can play with
- an IBOX. If you have more than one object (say an image and a string) which you
- would like to have selected all at once, you can insert them in a dialog, then
- cover them with an IBOX. Since the box is transparent, they will show through.
- If you now make the box selectable, clicking on it will highlight the whole area
- at once!
- .PP
- The G_BOXCHAR is just like a G_BOX, except that a single character is drawn
- in its center. They are mostly used as "control points": the FULLER, CLOSER,
- SIZER, and arrows in GEM windows are BOXCHARs, as are the components of the
- color selection gadgets in the RCS.
- .PP
- The OB_SPEC for box type objects is a packed bit array. Its various fields
- contain the background color and pattern, the border thickness and color, and
- the optional character and its color.
- .PP
- The string type objects are G_STRING, G_BUTTON, and G_TITLE. G_STRINGs (in
- addition to being a bad pun) are for setting up static explanatory text within
- dialogs. The characters are always written in the "system font": full size,
- black, with no special effects.
- .PP
- We have already discussed many of the uses of G_BUTTONs. They add a border
- around the text. The thickness of a G_BUTTON's border is determined by what
- flags are set for the object. All buttons start out with a border thickness of
- one pixel. One pixel is added if the EXIT attribute is set, and one more is
- added if the DEFAULT attribute is set.
- .PP
- The G_TITLE type is a specially formatted text string used only in the title
- bar of menus. This type is needed to make sure that the menus redraw correctly.
- The Resource Construction Set automatically handles inserting G_TITLEs, so you
- will seldom use them directly.
- .PP
- In a resource, the OB_SPEC for all string objects is a long pointer to a null
- terminated ASCII string. The string data in the C file is shown in the BYTE
- array rs_strings. Again you will notice that the OB_SPECs in the C file have
- been converted to indices into rs_string. To find the string which matches the
- object, take the value of OB_SPEC and count down that many lines in rs_strings.
- The next line is the correct string.
- .PP
- The formatted text object types are G_TEXT, G_BOXTEXT, G_FTEXT, and
- G_FBOXTEXT. G_TEXTs are a lot like strings, except that you can specify a
- color, different sizes, and a positioning rule for the text. Since they
- require more memory than G_STRINGs, G_TEXTs should be used sparingly to draw
- attention to important information within a dialog. G_TEXTs are also useful
- for automatic centering of dialog text which is changed at run-time. I will
- describe this technique in detail later on.
- .PP
- The G_BOXTEXT type adds a solid background and border to the G_TEXT type.
- These objects are occasionally used in place of G_BUTTONs when their color will
- draw attention to an important object.
- .PP
- The G_FTEXT object is an editable text field. You are able to specify a
- constant "template" of characters, a validation field for those characters which
- are to be typed in, and an initial value for the input characters. You may also
- select color, size, and positioning rule for G_FTEXTs. We'll discuss text
- editing at length below.
- .PP
- The G_FBOXTEXT object, as you might suspect, is the same as G_FTEXT with the
- addition of background and border. This type is seldom used: the extra
- appearance details distract attention from the text being edited.
- .PP
- The OB_SPEC for a formatted text object is a pointer to yet another type of
- structure: a TEDINFO. In the C file, you will find these in rs_tedinfo. Take
- the OB_SPEC value from each text type object and count down that many entries in
- rs_tedinfo, finding the matching TEDINFO on the next line. Each contains
- pointers to ASCII strings for the template, validation, and initialization. You
- can find these strings in rs_strings, just as above.
- .PP
- There are also fields for the optional background and border details, and for
- the length of the template and text. As we will see when discussing editing,
- the most important TEDINFO fields are the TE_PTEXT pointer to initialized text
- and the TE_TXTLEN field which gives its length.
- .PP
- The G_IMAGE object type is the only one of its kind. A G_IMAGE is a
- monochrome bit image. For examples, see the images within the various GEM alert
- boxes. Note that monochrome does not necessarily mean black. The image may be
- any color, but all parts of it are the SAME color. G_IMAGEs are used as visual
- cues in dialogs. They are seldom used as selectable items because their entire
- rectangle is inverted when they are clicked. This effect is seldom visually
- pleasing, particularly if the image is colored.
- .PP
- G_IMAGE objects have an OB_SPEC which is a pointer to a further structure
- type: the BITBLK. By now, you should guess that you will find it in the C file
- in the array rs_bitblk. The BITBLK contains fields describing the height and
- width of the image in pixels, its color,nd it also contains a long pointer to
- the actual bits which make up the image. In the C file, the images are encoded
- as hexadecimal words and stored in arrays named IMAG0, IMAG1, and so on.
- .PP
- The last type of object is the G_ICON. Like the G_IMAGE, the G_ICON is a bit
- image, but it adds a mask array which selects what portions of the image will be
- drawn, as well as an explanatory text field. A G_ICON may also specify
- different colors for its "foreground" pixels (the ones that are normally black),
- and its "background" pixels (which are normally white).
- .PP
- The pictures which you see in Desktop windows are G_ICONs, and so are the
- disks and trashcan on the desktop surface. With the latter you will notice the
- effects of the mask. The desktop shows through right up to the edge of the
- G_ICON, and only the icon itself (not a rectangle) is inverted when a disk is
- selected.
- .PP
- The OB_SPEC of an icon points to another structure called an ICONBLK. It is
- shown in the C file as rs_iconblk. The ICONBLK contains long pointers to its
- foreground bit array, to the mask bit array, and to the ASCII string of
- explanatory text. It also has the foreground and background colors as well as
- the location of the text area from the upper left of the icon. The most common
- use of G_ICONs and ICONBLKs is not in dialogs, instead they are used frequently
- in trees which are build at run-time, such as Desktop windows. In a future
- article, we will return to a discussion of building such "on-the-fly" trees with
- G_ICONs.
- .PP
- Now, let's recap the hierarchy of resource structures: The highest level
- structures are the resource header, and then the tree index. The tree index
- points to the beginning of each object tree. The objects making up the tree are
- of several types, and depending on that type, they may contain pointers to ASCII
- strings, or to TEDINFO, ICONBLK, or BITBLK structures. TEDINFOs contain further
- pointers to strings; BITBLKs have pointers to bit images; and ICONBLKs have
- both.
- .SH PUTTING IT TO WORK
- The most common situations requiring you to understand
- resource structures involve the use of text and editable text objects in
- dialogs. We'll look at two such techniques.
- .PP
- Often an application requires two or more dialogs which are very similar
- except for one or two title lines. In this circumstance, you can save a good
- deal of resource space by building only one dialog, and changing the title at
- run time.
- .PP
- It is easy to go wrong with this practice, however, because the obvious
- tactic of using a G_STRING and writing over its text at run time can go wrong.
- The first problem is that you must know in advance the longest title to be used,
- and put a string that long into the resource. If you don't you will damage other
- objects in the resource as you copy in characters. The other problem is that a
- G_STRING is always drawn at the same place in a dialog. If the length of the
- title changes from time to time, the dialog will have an unbalanced and sloppy
- appearance.
- .PP
- A better way to do this is to exploit the G_TEXT object type, and the TEDINFO
- structure. The set_text() routine in the download shows how. The parameters
- provided are the tree address, the object number, and the 32-bit address of the
- string to be substituted. For this to work, the object referenced should be
- defined as a G_TEXT type object. Additionally, the Centered text type should
- be chosen, and the object should have been "stretched" so that it fills the
- dialog box from side to side.
- .PP
- In the code, the first action is to get the OB_SPEC from the object which was
- referenced. Since we know that the object is a G_TEXT, the OB_SPEC must point
- to a TEDINFO. We need to change two fields in the TEDINFO. The TE_PTEXT field
- is the pointer to the actual string to be displayed; we replace it with the
- address of our new string. The TE_TXTLEN field is loaded with the new string's
- length. Since the Centered attribute was specified for the object, changing the
- TE_TXTLEN will cause the string to be correctly positioned in the middle of the
- dialog!
- .PP
- Editing text also requires working with the TEDINFO structure. One way of
- doing this is shown in the download. The object to be used (EDITOBJ) is assumed
- to be a G_FTEXT or G_FBOXTEXT. Since we will replace the initialized text at
- run time, that field may be left empty when building the object in the RCS.
- .PP
- The basic trick of this code is to point the TEDINFO's TE_PTEXT at a string
- which is defined in your code's local stack. The advantages of this technique
- are that you save resource space, save static data by putting the string in
- reusable stack memory, and automatically create a scratch string which may be
- discarded if the dialog is cancelled.
- .PP
- The text string shown is arbitrarily 41 characters long. You should give
- yours a length equal to the number of blanks in the object's template field plus
- one. Note that the code is shown as a segment, rather than a subroutine. This
- is required because the text string must be allocated within the context of
- dialog handling routine itself, rather than a routine which it calls!
- .PP
- After the tree address is found, the code proceeds to find the TEDINFO and
- modify its TE_PTEXT as described above. However, the length which is inserted
- into TE_TXTLEN must be the maximum string length, including the null!
- .PP
- The final line of code inserts a null into the first character of the
- uninitialized string. This will produce an empty editing field when the dialog
- is displayed. If there is an existing value for the object, you
- should instead use strcpy() to move it into text[]. Once the dialog is
- complete, you should check its final status as described in the last
- article. If an "OK" button was clicked, you will then use strcpy() to
- move the value in text[] back to its static location.
- .PP
- Although I prefer this method of handling editable text, another method
- deserves mention also. This procedure allocates a full length text string of
- blanks when creating the editable object in the RCS. At run-time, the TE_PTEXT
- link is followed to find this string's location in the resource, and any
- pre-existing value is copied in. After the dialog is run, the resulting value is
- copied back out if the dialog completed successfully.
- .PP
- Note that in both editing techniques a copy of the current string value is
- kept within the application's data area. Threading the resource whenever you
- need to check a string's value is extremely wasteful.
- .PP
- One final note on editable text objects: GEM's editor uses the commercial at
- sign '@' as a "meta-character". If it is the first byte of the initialized
- text, then the field is displayed blank no matter what follows. This can be
- useful, but is sometimes confusing when a user in all innocence enters an @ and
- has his text disappear the next time the dialog is drawn!
- .SH LETTERS, WE GET LETTERS
- The Feedback section on ANTIC ST ONLINE is now
- functional and is producing a gratifying volume of response. A number of
- requests were made for topics such as ST hardware and ST BASIC which are beyond
- the intended scope of this column. These have been referred to ANTIC's
- editorial staff for action.
- .PP
- So many good GEM questions were received that I will devote part of the next
- column to answering several of general interest. Also, your requests have
- resulting in scheduling future columns on VDI text output and on the principles
- (or mythology) of designing GEM application interfaces. Finally, a tip of the
- hat to the anonymous reader who suggested including the actual definitions of
- all macro symbols, so that those without the appropriate H files can follow
- along. As a result of this suggestion, the definitions for this column and the
- previous three are included at the end of the download. Future articles will
- continue this practice.
- .SH STRAW POLL!
- I'd like to make a practice of using the Feedback to get your
- opinions on the column's format. As a first trial, I'd like to know your
- feelings about my use of "portability macros" in the sample code. These macros,
- LLGET for example, are used for compatibility between 68K GEM systems like the
- ST, and Intel based systems like the IBM PC. This may be important to many
- developers. On the other hand, omitting them results in more natural looking C
- code. For instance, in the download you will find a second version of
- set_text() as described above, but without the portability macros. So, I would
- like to know if you think we should (A) Keep the macros - portability is
- important to serious developers, (B) Get rid of them - who cares about Intel
- chips anyway, or (C) Who cares? I'll tally the votes in two weeks and announce
- the results here.
- .SH STAY TUNED!
- As well as answers to feedback questions, the next column will
- discuss how GEM objects are linked to form trees, and how to use AES calls and
- your own code to manipulate them for fun and profit. In the following
- installment, we'll look at the VDI raster operations (also known as "blit"
- functions).
- .!
- .!
- .!*****************************************************************************
- .!* *
- .!* End Part 4 *
- .!* *
- .!*****************************************************************************
-